package com.client.koshercook.client;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;

public class UserIngredientsTable extends Composite {

	private ScrollPanel scrollerData;
	private VerticalPanel VPanel = new VerticalPanel();
	
	private VerticalPanel VPanelBottom = new VerticalPanel();
	private EdgesPanel edgesPanelBottom = new EdgesPanel(VPanelBottom);
	private VerticalPanel VPanelTop = new VerticalPanel();
	private EdgesPanel edgesPanelTop = new EdgesPanel(VPanelTop);
	private HorizontalPanel HBottomPanel = new HorizontalPanel();
	private VerticalPanel VIngPanel = new VerticalPanel();

	private CheckBox autoSearchCBox = new CheckBox("חיפוש אוטומטי");
	private PushButton searchButton = new PushButton("!חפש");
	private HorizontalPanel addPanel = new HorizontalPanel();
	private IngTextBox sBox = new IngTextBox();
	private PushButton addIngButton = new PushButton("הוסף");
	private FlexTable dataTableNames = new FlexTable(); // the ingredients table
	private FlexTable dataTable = new FlexTable(); // the ingredients table
	private PushButton clearAll = new PushButton("נקה חיפוש");
	private Filters filter = new Filters(); 

	//kosher panel {all/meat/dairy/parve}
	private HorizontalPanel kosherPanel = new HorizontalPanel();
	private RadioButton radioButtonAll = new RadioButton("kosherGroup", "");
	private RadioButton radioButtonMeat = new RadioButton("kosherGroup", "");
	private RadioButton radioButtonDairy = new RadioButton("kosherGroup", "");
	private RadioButton radioButtonParve = new RadioButton("kosherGroup", "");
	private ListBox recType = new ListBox();
	
	private HTML infoText = new HTML("הכנס מצרכים שברשותך");
	private HTML infoText1 = new HTML("בחר את סוג הכשרות");
	private HTML infoText2 = new HTML("בחר את סוג המנה");
	
	//ingredient number limit
	private int ingLimit;
	private boolean usingScroller = false;
	
	public UserIngredientsTable(int windowHeight) {

		if (windowHeight > 1000)
			ingLimit = 13;
		else if (windowHeight > 800)
			ingLimit = 10;
		else if (windowHeight > 600)
			ingLimit = 7;
		else 
			ingLimit = 4;

		VPanelTop.setStyleName("ingsPanelEdges");
		VPanelBottom.setStyleName("ingsPanelEdges");
		
		VPanel.add(edgesPanelTop);
		VPanel.add(new Image("spacer.gif"));
		VPanel.add(edgesPanelBottom);
		
				
		// creating the 'add panel'
		addIngButton.setTitle("לחץ להוספת רכיבים");
		addIngButton.setSize("80", "20");
		addPanel.add(addIngButton);
		addPanel.add(sBox);
		addPanel.setSpacing(2);
		addPanel.addStyleName("addPanel");
		
		searchButton.setSize("80", "20");
		searchButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				//check the user enter ingredients
				if(Client.model.request.isIngsEmpty())
					Client.model.quickPopup2("יש להכניס לפחות רכיב אחד");
				else{
					Client.model.resetPage();
					Client.model.sendRequest();
				}
			}
		});
		
		autoSearchCBox.addValueChangeHandler(new ValueChangeHandler<Boolean>(){
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				Client.model.setAutoSearch(event.getValue());
				Client.model.resetPage();
				Client.model.sendRequest();
			}
		});
		autoSearchCBox.setTitle("לחץ כדי לבצע חיפוש אוטומטי לאחר כל שינוי במרכיבי החיפוש");
		
		
		// creating the 'kosher type panel'
		radioButtonAll.setValue(true);
		radioButtonAll.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				Client.model.setKosherAll();
			}
		});
		radioButtonMeat.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				Client.model.setKosherMeat();
			}
		});
		radioButtonDairy.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				Client.model.setKosherDairy();
			}
		});
		radioButtonParve.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				Client.model.setKosherParve();
			}
		});
		kosherPanel.add(radioButtonAll);
		kosherPanel.add(new Image("kosher_types_trans.gif", 0, 87, 37, 21));	//all image
		kosherPanel.add(radioButtonMeat);
		kosherPanel.add(new Image("kosher_types_trans.gif", 0, 59, 47, 21));	//meat image
		kosherPanel.add(radioButtonDairy);
		kosherPanel.add(new Image("kosher_types_trans.gif", 0, 29, 47, 21));	//dairy image
		kosherPanel.add(radioButtonParve);
		kosherPanel.add(new Image("kosher_types_trans.gif", 0, 0, 47, 21));		//parve image

		//creating the drop-down rec-type menu
		recType.addItem("הכל");
		recType.addItem("מנות ראשונות");
		recType.addItem("בשר ודגים");
		recType.addItem("מרקים");
		recType.addItem("תוספות");
		recType.addItem("סלטים");
		recType.addItem("לחמים");
		recType.addItem("קינוח");
		recType.addItem("עוגות");
		recType.addItem("אחר");
		recType.setStyleName("gwt-TextBox");
		recType.addChangeHandler(new ChangeHandler(){
			public void onChange(ChangeEvent event) {
				String type = recType.getItemText(recType.getSelectedIndex());
				Client.model.setType(type);
			}
		});
		
		// creating the table for the ingredients
		dataTableNames.setText(0, 1, "  מצרכים ");
		dataTableNames.setText(1, 0, "  חובה במתכון ");
		dataTableNames.setText(1, 1, " שם ");
		dataTableNames.setText(1, 2, "  הסר ");
		dataTableNames.setText(1, 3, " ");
		dataTableNames.setCellPadding(1);
		dataTableNames.setStyleName("dataTable");
		dataTableNames.getColumnFormatter().setWidth(0, "84px");
		dataTableNames.getColumnFormatter().setWidth(1, "110px");
		dataTableNames.getColumnFormatter().setWidth(2, "10px");
		dataTableNames.getColumnFormatter().setWidth(3, "14px");
		
		dataTable.setText(0, 1, "  מצרכים ");
		dataTable.setText(1, 0, "  חובה במתכון ");
		dataTable.setText(1, 1, "  שם ");
		dataTable.setText(1, 2, "  הסר ");
		dataTable.setCellPadding(1);
		dataTable.setStyleName("dataTable");
		dataTable.getColumnFormatter().setWidth(0, "90px");
		dataTable.getColumnFormatter().setWidth(1, "116px");
		dataTable.getColumnFormatter().setWidth(2, "10px");
		
		// creating the main panel
		infoText.setStyleName("infoText2");
		infoText1.setStyleName("infoText2");
		infoText2.setStyleName("infoText2");
		
		VPanelTop.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE);
		VPanelTop.setHorizontalAlignment(HasAlignment.ALIGN_RIGHT);
		VPanelTop.setSpacing(5);
		
		VPanelTop.add(infoText);
		VPanelTop.add(addPanel);
		
		VIngPanel.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE);
		VIngPanel.setHorizontalAlignment(HasAlignment.ALIGN_RIGHT);
		VIngPanel.setSpacing(0);
		VIngPanel.add(dataTable);
		
		VPanelBottom.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE);
		VPanelBottom.setHorizontalAlignment(HasAlignment.ALIGN_RIGHT);
		VPanelBottom.setSpacing(5);
		
		VPanelBottom.add(infoText1);
		VPanelBottom.add(kosherPanel);
		HorizontalPanel HPanel = new HorizontalPanel();
		HPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
		HPanel.add(searchButton);
		HPanel.add(recType);
		HPanel.add(infoText2);
		VPanelBottom.add(HPanel);
		VPanelBottom.add(autoSearchCBox);
		VPanelBottom.add(VIngPanel);
		
		clearAll.setSize("90", "20");
		filter.setSize("90", "20");
		
		HBottomPanel.add(clearAll);
		HBottomPanel.add(filter);
		HBottomPanel.setSpacing(10);
		HBottomPanel.setCellHorizontalAlignment(clearAll, HasAlignment.ALIGN_LEFT);
		HBottomPanel.setCellHorizontalAlignment(clearAll, HasAlignment.ALIGN_RIGHT);
		
		VPanelBottom.add(HBottomPanel);
		VPanelBottom.setCellHorizontalAlignment(HBottomPanel,HasHorizontalAlignment.ALIGN_CENTER);
		// move cursor focus to the text box
		sBox.setFocus(true);
		
		// Listen for mouse events on the add new ingredient button.
		addIngButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				addIngredient();
			}
		});
		sBox.getTextBox().addKeyPressHandler(new KeyPressHandler(){
			public void onKeyPress(KeyPressEvent event) {
				if (event.getCharCode() == KeyCodes.KEY_ENTER) {
					if (!sBox.isPressed()){	//this is used to prevent adding both the typed ingredient and the suggest box ingredient
						addIngredient();
					}
					sBox.resetPress();
				}
				else	//user has changed his selection (used up or down), now if he'll press enter, only the suggest box ingredient will be added
					sBox.setPressed();
			}
		});
        sBox.addSelectionHandler(new SelectionHandler<Suggestion>(){
                public void onSelection(SelectionEvent<Suggestion> event) {
                        addIngredient();
                }
        });
        //Listen for mouse events on the clear all button
        clearAll.addClickHandler(new ClickHandler() {
			
			public void onClick(ClickEvent event) {
				Client.model.clearSearch();
				if (usingScroller)
					destroyScrollIng();
				else
					clearIngsTable(dataTable);
				filter.reset();
				sBox.setText("הכנס שם רכיב");
			}
		});
        
        clearAll.setTitle("הסר את כל הרכיבים מרשימת החיפוש ואת תוצאות החיפוש");
        
        initWidget(VPanel);
	}

	
	/** use this to add ing from another class */	//TODO: can make this happen without using sBox
	public void addIngredient(String ingName){
		sBox.setText(ingName);
		addIngredient();
	}
	
	/** Add Ingredient to FlexTable. Executed when the user clicks the
	 * addIngButton or presses enter in the IngNameTextBox. */
	private void addIngredient() {
		
		final String ingName = sBox.getText();
		sBox.setText(""); // clear the textBox
		
		sBox.setFocus(true);
		// Ingredient name must be legal
		if (ingName == null || ingName == "" || ingName.startsWith(" ")	|| !ingName.matches("^[א-ת \\']{1,15}$")) {
			sBox.setText("שם לא חוקי");
			return;
		}
		// Check if ingredient name is known to server
		if (!Client.model.serverKnowsIngName(ingName)) {
			sBox.setText("שם רכיב לא מוכר");
			return;
		}

		if (!Client.model.addIngredient(ingName)) // if ingName is already in the list, do not add it to the table
			return;

		// Add the Ingredient to the table.
		int ingSize = Client.model.request.getIng().size(); 
		if(ingSize == ingLimit+1){ //move to scroll panel
			createScrollIng();
		}
		else{
			if (usingScroller)
				addIngToDataTable(ingName,0);
			else
				addIngToDataTable(ingName,2);
		}

	}

	/** add one ingredient to a data table */
	private void addIngToDataTable(final String ingName,final int jump){
		int row = dataTable.getRowCount();
		dataTable.setText(row, 1, ingName);

		// Add a button to remove this ingredient from the table
		PushButton removeIngButton = new PushButton(new Image("remove.gif"));
		removeIngButton.setTitle("לחץ להסרת הרכיב מהחיפוש");
		removeIngButton.setStyleName("empty");
		removeIngButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				int indx = Client.model.request.ingsIndexOf(ingName);
				dataTable.removeRow(indx + jump);
				Client.model.removeIngredient(ingName);
				if (Client.model.request.getIng().size() == ingLimit)
					destroyScrollIng();
			}
		});
		
		dataTable.setWidget(row, 2, removeIngButton);

		// Add a button to include this ingredient in the "must" list
		CheckBox mustButton = new CheckBox();
		mustButton.setTitle("סמן כדי לקבל מתכונים שבהכרח כוללים רכיב זה");
		if (Client.model.request.mustIngs.contains(ingName))
			mustButton.setValue(true);
		mustButton.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
			public void onValueChange(ValueChangeEvent<Boolean> event) {
				Client.model.setIngredientMust(ingName, event.getValue());
			}
		});
		dataTable.setWidget(row, 0, mustButton);
		
	}
	
	/** change table structure. re built old data */
	public void createScrollIng(){
		VIngPanel.remove(dataTable);		
		VIngPanel.add(dataTableNames);
		
		// making the data scroll-able

		scrollerData = new ScrollPanel(dataTable);
		scrollerData.setSize("250px", (ingLimit*25)+"px");
		
		VIngPanel.add(scrollerData);
		dataTable.removeAllRows();
		for (String ing : Client.model.request.getIng())
			addIngToDataTable(ing, 0);
		usingScroller = true;
	}
	
	/** change table structure. re built old data */
	public void destroyScrollIng(){
		VIngPanel.remove(dataTableNames);
		VIngPanel.remove(scrollerData);
		VIngPanel.add(dataTable);
		dataTable.removeAllRows();
		dataTable.setText(0, 1, "  מצרכים ");
		dataTable.setText(1, 0, "  חובה במתכון ");
		dataTable.setText(1, 1, "  שם ");
		dataTable.setText(1, 2, "  הסר ");
		for (String ing : Client.model.request.getIng())
			addIngToDataTable(ing, 2);
		usingScroller = false;
	}
	
	public void setSmaller(){
		VPanelBottom.remove(infoText);
		infoText1.setHTML("בחר את סוג הכשרות");
	}
	
	/** clear a single Ingredients table */
	private void clearIngsTable(FlexTable recipesTable) {
		while (recipesTable.getRowCount() > 2)
			recipesTable.removeRow(2);
	}
	
	/** set autoSearchChecker */
	public void setAutoSearchChecker(boolean checked){
		autoSearchCBox.setValue(checked);
	}
}
